module.exports = {


  friendlyName: 'Download unpatched hosts CSV',


  description: 'Download unpatched hosts for a software type file (returning a stream).',


  inputs: {
    exportType: {
      required: true,
      type: 'string',
      description: 'The type of CSV export that will be generated',
      isIn: [
        'operatingSystem',
        'chrome',
        'firefox',
        'safari',
        'microsoftOffice',
        'flash',
      ]
    },
    teamApid: {
      description: 'The ID of the Team to filter by, or 0 to only include hosts with no team, or undefined to not filter by any team.',
      type: 'number',
    },
  },


  exits: {
    success: {
      outputFriendlyName: 'File',
      outputDescription: 'The streaming bytes of the file.',
      outputType: 'ref'
    },
  },


  fn: async function ({exportType, teamApid}) {
    // Generate a random room name.
    let roomId = await sails.helpers.strings.random();
    if(this.req.isSocket) {
      // Add the requesting socket to the room.
      sails.sockets.join(this.req, roomId);
    }

    let stream = require('stream');
    let csvString = '';
    // Create a writeable stream we'll use to create the csvString.
    let writableStream = new stream.Writable({//[?]: https://nodejs.org/api/stream.html#writable_writechunk-encoding-callback
      write(chunk, encoding, callback) {
        csvString += chunk.toString();
        callback();
      }
    });

    let csv = require('fast-csv');
    let generatingCsv = csv.format({headers: true});
    // Pass the writableStream into generatingCsv.
    generatingCsv.pipe(writableStream);// [?]: https://c2fo.github.io/fast-csv/docs/formatting/methods#write


    if(exportType === 'operatingSystem'){
      // If exportType is operatingSystem, we
      // Get the non-compliant operating systems
      let nonCompliantOperatingSystems = await OperatingSystem.find({isCompliant: false});
      // Note, if teamApid is undefined, this will get find hosts from all teams.
      let hostsWithNonCompliantOperatingSystems = await Host.find({teamApid: teamApid, operatingSystem: {in: _.pluck(nonCompliantOperatingSystems, 'id')}}).populate('operatingSystem');
      for(let host of hostsWithNonCompliantOperatingSystems){
        let csvRowForThisHost = {};
        csvRowForThisHost['Host display name'] = host.displayName;
        csvRowForThisHost['OS name'] = host.operatingSystem.name;
        csvRowForThisHost['OS version'] = host.operatingSystem.versionName;
        csvRowForThisHost['Host Fleet URL'] = sails.config.custom.fleetBaseUrl + '/hosts/'+host.fleetApid;
        csvRowForThisHost['Host serial number'] = host.hardwareSerialNumber;
        csvRowForThisHost['Host team'] = host.teamDisplayName;
        csvRowForThisHost['Host team ID'] = host.teamApid;
        generatingCsv.write(csvRowForThisHost);
      }
    } else {
      let userFriendlyPlatformNamesByCodeName = {
        'darwin': 'macOS',
        'windows': 'Windows',
        'chrome': 'Chrome OS',
        'ubuntu': 'Ubuntu',
        'linux': 'Linux'
      };
      let hostIdsOnThisTeam = await Host.find({teamApid: teamApid}).select('id');
      let nonComplaintSoftwareInstalls = await CriticalInstall.find({isCompliant: false, softwareType: exportType, host: {in: _.pluck(hostIdsOnThisTeam, 'id')}}).populate('host');
      for(let install of nonComplaintSoftwareInstalls) {
        let userFriendlyPlatformNameForThisVersion = userFriendlyPlatformNamesByCodeName[install.platform];
        if(userFriendlyPlatformNameForThisVersion === undefined){
          userFriendlyPlatformNameForThisVersion = install.platform;
        }
        let csvRowForThisInstall = {};
        csvRowForThisInstall['Host display name'] = install.host.displayName;
        csvRowForThisInstall['Software name'] = _.capitalize(install.softwareName);
        csvRowForThisInstall['Software platform'] = userFriendlyPlatformNameForThisVersion;
        csvRowForThisInstall['Software version'] = install.versionName;
        csvRowForThisInstall['Host Fleet URL'] = sails.config.custom.fleetBaseUrl + '/hosts/'+install.host.fleetApid;
        csvRowForThisInstall['Host serial number'] = install.host.hardwareSerialNumber;
        csvRowForThisInstall['Host team'] = install.host.teamDisplayName;
        csvRowForThisInstall['Host team ID'] = install.host.teamApid;
        generatingCsv.write(csvRowForThisInstall);
      }
    }

    generatingCsv.end();
    // After the the csvString has been generated by the writableStream, broadcast the csvString to the requesting user's socket.
    writableStream.on('finish', () => {
      if(this.req.isSocket){
        // Note: we're sending the cveId with the cvsString, this is so we can set the filename in our frontend code.
        sails.sockets.broadcast(roomId, 'csvExportDone', csvString);
        // Unsubscribe the socket from the room.
        sails.sockets.leave(this.req, roomId);
      } else {
        return csvString;
      }
    });
  }


};
